home *** CD-ROM | disk | FTP | other *** search
/ Workbench Design / WB Collection.iso / workbench werkzeuge / cpu tools / cpuload / cpuload.c < prev    next >
C/C++ Source or Header  |  1996-04-07  |  7KB  |  349 lines

  1. /*
  2.     CPULoad
  3.     (C) Thomas Radtke 1994
  4.  
  5.     main:        Process, Initialisierungen und buisy loop
  6.     druck:        Task, Graphische Ausgabe
  7.     IdleIrq:    IRQ server, Auswertung des buisy loop
  8.  
  9.     Um double-Rechnungen zu vermeiden werden ULONG's in beide Richtungen
  10.     geshiftet. Bei hohen Rechenleistungen kann dies ggf. zu Überläufen
  11.     führen. Abhilfe bringt eine Verringerung des 'aktuell'-Wertes
  12.     ('aktuell>>n') um ein geeignetes n.
  13.  
  14.     Das Abbruchsignal ist CTRL-D. Niemals CTRL-C verwenden, wenn der
  15.     Compiler dieses Signal als generellen Abbruch benutzt.
  16.  
  17.     Basiert auf Idle LED von Lindsay Meek.
  18.  
  19.     read the README !
  20. */
  21.  
  22. char *dummy="$VER: CPULoad 1.0ß";
  23.  
  24. #include <intuition/intuitionbase.h>
  25. #include <exec/nodes.h>
  26. #include <exec/tasks.h>
  27. #include <exec/interrupts.h>
  28. #include <hardware/intbits.h>
  29. #include <libraries/dos.h>
  30. #include <exec/types.h>
  31. #include <exec/memory.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <signal.h>
  35.  
  36. /*    Stacksize für den Grafik-Task (1000 < STACK_SIZE < 10000)    */
  37.  
  38. #define STACK_SIZE 10000L
  39.  
  40. /*    Task name und Pointer für Task Struktur    */
  41.  
  42. struct Task *task = NULL;
  43. char *taskname = "CPULoad";
  44.  
  45. struct timerequest *tr;
  46. struct MsgPort *tport;
  47. struct Message *msg;
  48. struct Window *CustWindow;
  49. struct IntuitionBase *IntuitionBase;
  50. struct GfxBase *GfxBase;
  51.  
  52. #define rp CustWindow->RPort
  53.  
  54. struct NewWindow BlankWindow=
  55. {
  56.     175,24,130,50,1,0,
  57.     CLOSEWINDOW | NEWSIZE | RAWKEY,
  58.     WINDOWSIZING | ACTIVATE | GIMMEZEROZERO | SMART_REFRESH | WINDOWCLOSE | WINDOWDRAG | WINDOWDEPTH,
  59.     0,0,
  60.     "CPULoad",
  61.     0,0,70,20,0,0,
  62.     PUBLICSCREEN
  63. };
  64.  
  65. unsigned int maximum,aktuell;
  66.  
  67. /*    globale Kopie des Main-Prozesses für druck() (wegen der Signale)    */
  68.  
  69. struct Task *met2;
  70.  
  71. /*    System structure name    */
  72.  
  73. #define UTILITY_NAME "IdleCPU"
  74.  
  75. /*    various counters used to detect the idle state in the vblank    */
  76.  
  77. static ULONG idle_vbi_cnt_limit[3];
  78.  
  79. /*    allocate the timer    */
  80.  
  81. struct timerequest *create_timer(ULONG unit)
  82. {
  83.     LONG error;
  84.     struct MsgPort *timerport;
  85.     struct timerequest *timermsg;
  86.  
  87.     if ((timerport=(struct MsgPort *)CreatePort(0,0))==NULL) exit(1);
  88.     if ((timermsg=(struct timerequest *)CreateExtIO(timerport,sizeof(struct timerequest)))==NULL) exit(1);
  89.     if ((error=OpenDevice(TIMERNAME,unit,(struct IORequest *)timermsg,0))!=0) exit(1);
  90.     return(timermsg);
  91. }
  92.  
  93. /*    Läuft im VBL-Interrupt    */
  94.  
  95. int IdleCPU()
  96. {
  97.     idle_vbi_cnt_limit[0]=1;
  98.     aktuell=idle_vbi_cnt_limit[1];
  99.     idle_vbi_cnt_limit[1]=0;
  100.     return 0;
  101. }
  102.  
  103. /*    Läuft als Task    */
  104.  
  105. druck()
  106. {
  107.     struct IntuiMessage *message;    /*    Windowclose    */
  108.     struct IntuiMessage *GetMsg();
  109.     struct timeval updateval;    /*    1/10 Sekunde    */
  110.     char name[256];            /*    PubScreen    */
  111.     int n;
  112.     unsigned int sum;        /*    Summand der freien Zyklen    */
  113.     unsigned int height,width,right,bottom;
  114.     unsigned int int_pix_per_load;        /*    Skalierung    */
  115.     int whitepen,blackpen;
  116.     struct Screen *PubScreen;
  117.     short pen,minpen,maxpen;
  118.     unsigned short RGB;
  119.     int class;
  120.  
  121. /*    init timer    */
  122.  
  123.     tr=create_timer(UNIT_MICROHZ);
  124.  
  125.     updateval.tv_secs=0;
  126.     updateval.tv_micro=100000;    /*    1/10 secs    */
  127.  
  128.     IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0);
  129.     GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
  130.  
  131.     GetDefaultPubScreen(name);
  132.     PubScreen=(struct Screen *)LockPubScreen(name);
  133.     UnlockPubScreen(0L,PubScreen);
  134.  
  135.     BlankWindow.MaxHeight=PubScreen->Height;
  136.     BlankWindow.MaxWidth=PubScreen->Width;
  137.  
  138.     CustWindow=(struct Window *)OpenWindow(&BlankWindow);
  139.  
  140. /*    Farbgebung aus der ColorMap bestimmen (SunClock-Methode)    */
  141.  
  142.     whitepen = 1;
  143.     blackpen = 0;
  144.     maxpen=0x000;
  145.     minpen=0xfff;
  146.  
  147.     for (n=0; n<1<<PubScreen->BitMap.Depth; n++)
  148.     {
  149.         RGB = GetRGB4(PubScreen->ViewPort.ColorMap,n);
  150.  
  151.         pen = (RGB & 0x00f) + ((RGB & 0x0f0) >> 4) + ((RGB & 0xf00) >> 8);
  152.  
  153.         if (pen < minpen)
  154.         {
  155.             minpen = pen;
  156.             blackpen = n;
  157.         }
  158.         if (pen > maxpen)
  159.         {
  160.             maxpen = pen;
  161.             whitepen = n;
  162.         }
  163.     }
  164.  
  165.     height=CustWindow->GZZHeight;
  166.     width=CustWindow->GZZWidth;
  167.     right=width-1;
  168.     bottom=height-1;
  169.  
  170. /*    Ja, ja, mach mich Weiß !    */
  171.  
  172.     SetAPen(rp,whitepen);
  173.     RectFill(rp,0,0,right,bottom);
  174.  
  175. /*    FOREVER    */
  176.  
  177.     while (1)
  178.     {
  179.         sum=0;            /*    Zyklenzähler    */
  180.         for (n=0; n<10; n++)
  181.         {
  182.  
  183. /*    Akkumuliere CPU-Auslastung    */
  184.  
  185.             sum+=aktuell;
  186.  
  187. /*    wait for 1/10 secs to give others a chance    */
  188.  
  189. /*    Delay() funktioniert nicht, weil dos nicht erwünscht in task    */
  190.  
  191.             tr->tr_node.io_Command=TR_ADDREQUEST;
  192.             tr->tr_time=updateval;
  193.             DoIO((struct IORequest *)tr);
  194.         }
  195.  
  196.         sum/=10;    /*    Average    */
  197.  
  198. /*    Verschiebe Bild nach links    */
  199.  
  200.         height=CustWindow->GZZHeight;
  201.         width=CustWindow->GZZWidth;
  202.         right=width-1;
  203.         bottom=height-1;
  204.  
  205.         int_pix_per_load=(height<<16)/maximum;
  206.  
  207.         ScrollRaster(rp,1,0,0,0,width,height);
  208.  
  209. /*    Jede Sekunde Ausdruck    */
  210.  
  211.         SetAPen(rp,blackpen);
  212.         Move(rp,right,bottom);
  213.  
  214.         Draw(rp,right,(sum*int_pix_per_load)>>16);
  215.         if (rp->cp_y)
  216.         {
  217.             SetAPen(rp,whitepen);
  218.             Draw(rp,right,0);
  219.         }
  220.  
  221. /*
  222.     Dies ist der gefährliche Teil des Universums. Falls das nicht auf allen
  223.     Maschinen läuft, zum testen rausschmeissen
  224. */
  225.  
  226.         message=GetMsg(CustWindow->UserPort);
  227.         if ((class=message->Class)==CLOSEWINDOW)
  228.         {
  229.             ReplyMsg(message);        /*    !!!    */
  230.             Signal(met2,SIGBREAKF_CTRL_D);    /*    Kill all tasks    */
  231.         }
  232.         else if (class==NEWSIZE)
  233.         {
  234.             ReplyMsg(message);
  235.             SetAPen(rp,whitepen);
  236.             RectFill(rp,0,0,right,bottom);
  237.         }    
  238.         else if (class==RAWKEY)
  239.         {
  240.             if (message->Code==89) WindowToFront(CustWindow);
  241.             ReplyMsg(message);
  242.         }
  243.     }
  244. }
  245.  
  246. /* Run this as a process. It aborts when it detects a CTRL_D signal */
  247.  
  248. main()
  249. {
  250.     extern struct Task *FindTask(char *);
  251.     struct Task *met;
  252.     struct Interrupt mei;
  253.     WORD oldpri;
  254.     char *oldname;
  255.     int i;
  256.  
  257. /*    switch off CTRL_C handling    */
  258.  
  259.     signal(SIGINT,SIG_IGN);
  260.  
  261.     met=FindTask(UTILITY_NAME);    /*    Gibts mich schon ?    */
  262.  
  263.     if (met!=NULL)            /*    Jawoll.    */
  264.     {
  265.  
  266. /* Send CTRL_D signal to task */
  267.  
  268.         Signal(met,SIGBREAKF_CTRL_D);    /*    dann Adieu !    */
  269.         exit(1);            /*    +-:-)    */
  270.     }
  271.  
  272. /*    setup für IRQ    */
  273.  
  274.     mei.is_Node.ln_Type = NT_INTERRUPT;
  275.     mei.is_Node.ln_Pri  = -127;
  276.     mei.is_Node.ln_Name = UTILITY_NAME;
  277.     mei.is_Data = (APTR)0; /* idle_vbi_cnt_limit; */
  278.     mei.is_Code = IdleCPU;
  279.  
  280.     AddIntServer(INTB_VERTB, &mei);        /*    Install IRQ server    */
  281.  
  282.     met=FindTask(NULL);            /*    Finde mich selber    */
  283.     oldpri=met->tc_Node.ln_Pri;        /*    Save old priority    */
  284.     oldname=met->tc_Node.ln_Name;        /*    Save old name    */
  285.  
  286. /*    Redirect task name, damit niemand durch rename die gute Absicht vereitelt    */
  287.  
  288.     met->tc_Node.ln_Name=UTILITY_NAME;
  289.  
  290.     met->tc_Node.ln_Pri=40;        /*    Raise priority for calibration    */
  291.  
  292.     met2=met;    /*    Pointer für druck()    */
  293.  
  294. /*    reset counters    */
  295.  
  296.     idle_vbi_cnt_limit[0]=0;
  297.     idle_vbi_cnt_limit[1]=0;
  298.     idle_vbi_cnt_limit[2]=0;
  299.  
  300. /*    wait for next vbi, nicht ganz astrein    */
  301.  
  302.     Forbid();
  303.  
  304.     while(idle_vbi_cnt_limit[0]==0) ;
  305.  
  306. /*    count # of increments in one frame (for calibration)    */
  307.  
  308.     idle_vbi_cnt_limit[2]=0;
  309.     idle_vbi_cnt_limit[0]=0;
  310.     while (idle_vbi_cnt_limit[0]==0) idle_vbi_cnt_limit[2]++;
  311.  
  312.     Permit();
  313.  
  314. /*    druck() braucht maximum    */
  315.  
  316.     maximum=idle_vbi_cnt_limit[2];
  317.  
  318. /*    printf("%d\n",maximum);    */
  319.  
  320. /*    und endlich...trara !    */
  321.  
  322.     task=CreateTask(taskname,30,druck,STACK_SIZE);
  323.  
  324.     met->tc_Node.ln_Pri=-127;
  325.  
  326. /*    Busy loop for eating up idle cpu cycles    */
  327.  
  328.     while((met->tc_SigRecvd & SIGBREAKF_CTRL_D)==0)    /*    Abort on CTRL_D    */
  329.     {
  330.         idle_vbi_cnt_limit[1]++;    /*    Increment idle counter    */
  331.     }
  332.  
  333. /*    und Tschüs    */
  334.  
  335.     RemIntServer(INTB_VERTB,&mei);    /*    Remove IRQ server    */
  336.     met->tc_Node.ln_Pri=oldpri;    /*    Change priority back    */
  337.     met->tc_Node.ln_Name=oldname;    /*    Change name back    */
  338.  
  339.     Forbid();
  340.     DeleteTask(task);
  341.     Permit();
  342.  
  343.     CloseWindow(CustWindow);
  344.     CloseLibrary(IntuitionBase);
  345.     CloseLibrary(GfxBase);
  346.  
  347.     exit(1);
  348. }
  349.